package com.wxzhou.wangzhuan.repository;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wxzhou.wangzhuan.dto.AccountChangeType;
import com.wxzhou.wangzhuan.dto.WithdrawRecordRequestDto;
import com.wxzhou.wangzhuan.dto.WithdrawRecordResponseDto;
import com.wxzhou.wangzhuan.entity.*;
import com.wxzhou.wangzhuan.service.PayService;
import com.wxzhou.wangzhuan.util.JsonMapUtil;
import io.smallrye.mutiny.Uni;
import io.vertx.core.json.JsonObject;
import io.vertx.mutiny.sqlclient.Pool;
import io.vertx.mutiny.sqlclient.Row;
import io.vertx.mutiny.sqlclient.Tuple;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.jboss.logging.Logger;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 用户提现持久层
 */
@ApplicationScoped
public class WithdrawRepository {

    private static final Logger LOG = Logger.getLogger(WithdrawRepository.class);

    @Inject
    Pool client;

    @Inject
    ObjectMapper objectMapper;

    public Uni<List<WithdrawRecordResponseDto>> findWithPagination(WithdrawRecordRequestDto pageRequest) {
        QueryConditionUtil queryCoinlogStrBy = createQueryStrBy(pageRequest);
        StringBuilder sql = queryCoinlogStrBy.getPageStr();
        List<Object> pageParams = queryCoinlogStrBy.getPageParams();
        return client.preparedQuery(sql.toString())
                .execute(Tuple.from(pageParams))
                .onItem().transform(rows -> {
                    List<WithdrawRecordResponseDto> configs = new ArrayList<>();
                    for (Row row : rows) {
                        WithdrawRecordResponseDto responseDto = mapRowToPageRecord(row);
                        BigDecimal newAmount = responseDto.getAmount().divide(new BigDecimal("100")).setScale(4, RoundingMode.DOWN);
                        responseDto.setAmount(newAmount);
                        configs.add(responseDto);
                    }
                    return configs;
                });
    }

    public Uni<Long> countOf(WithdrawRecordRequestDto pageRequest) {
        QueryConditionUtil queryCoinlogStrBy = createQueryStrBy(pageRequest);
        List<Object> paramList = queryCoinlogStrBy.getParams();

        Tuple params = paramList.isEmpty() ? Tuple.tuple() : Tuple.from(paramList);

        return client.preparedQuery(queryCoinlogStrBy.getQueryStr().toString())
                .execute(params)
                .onItem().transform(rows -> {
                    if (rows.size() > 0) {
                        return rows.iterator().next().getLong("count");
                    }
                    return 0L;
                });
    }

    private QueryConditionUtil createQueryStrBy(WithdrawRecordRequestDto pageRequest) {

        QueryConditionUtil queryConditionUtil = new QueryConditionUtil();
        StringBuilder sql = new StringBuilder("SELECT DISTINCT a.* FROM wz_user_withdrawals a  WHERE a.id is not null ");

        List<Object> params = new ArrayList<>();

        int size = pageRequest.getLimit();
        int offset = pageRequest.getOffset();

        sql.append(" AND a.user_id = $").append(params.size() + 1);
        params.add(pageRequest.getUserid());
        sql.append(" ORDER BY a.created_at DESC ");
        queryConditionUtil.setQueryStr(sql);

        queryConditionUtil.setParams(params);
        List<Object> pageParams = new ArrayList<>();
        pageParams.addAll(params);

        StringBuilder pageSql = new StringBuilder(sql.toString());
        // 分页
        pageSql.append(" LIMIT $").append(pageParams.size() + 1);
        pageParams.add(size);
        pageSql.append(" OFFSET $").append(pageParams.size() + 1);
        pageParams.add(offset);

        queryConditionUtil.setPageStr(pageSql);
        queryConditionUtil.setPageParams(pageParams);

        StringBuilder countStr = new StringBuilder("SELECT COUNT(*) as count FROM  (").append(sql).append(") c ");
        queryConditionUtil.setQueryStr(countStr);
        return queryConditionUtil;
    }


    /**
     * 查询用户当日提现次数
     *
     * @param userId 用户ID
     * @return 当日提现次数
     */
    public Uni<Integer> countDailyWithdrawals(Long userId) {
        LocalDateTime today = LocalDateTime.now();
        String sql = "SELECT COUNT(*) FROM wz_user_withdrawals WHERE user_id = $1 AND created_at >= $2";
        return client.preparedQuery(sql)
                .execute(Tuple.of(userId, today))
                .onItem().transform(rows -> rows.iterator().next().getInteger(0));
    }

    /**
     * 查询用户当日提现总金额
     *
     * @param userId 用户ID
     * @return 当日提现总金额（单位：分）
     */
    public Uni<BigDecimal> sumDailyWithdrawalAmount(Long userId) {
        LocalDateTime today = LocalDateTime.now();
        String sql = "SELECT COALESCE(SUM(amount), 0) FROM wz_user_withdrawals WHERE user_id = $1 AND created_at >= $2";
        return client.preparedQuery(sql)
                .execute(Tuple.of(userId, today))
                .onItem().transform(rows -> rows.iterator().next().getBigDecimal(0));
    }

    /**
     * 查询用户特定金额的提现次数
     *
     * @param userId 用户ID
     * @param amount 提现金额（单位：分）
     * @return 特定金额的提现次数
     */
    public Uni<Integer> countWithdrawalsByAmount(Long userId, BigDecimal amount) {
        String sql = "SELECT COUNT(*) FROM wz_user_withdrawals WHERE user_id = $1 AND amount = $2";
        return client.preparedQuery(sql)
                .execute(Tuple.of(userId, amount))
                .onItem().transform(rows -> rows.iterator().next().getInteger(0));
    }

    /**
     * 查询用户累计提现次数
     *
     * @param userId 用户ID
     * @return 累计提现次数
     */
    public Uni<Integer> countTotalWithdrawals(Long userId) {
        String sql = "SELECT COUNT(*) FROM wz_user_withdrawals WHERE user_id = $1";
        return client.preparedQuery(sql)
                .execute(Tuple.of(userId))
                .onItem().transform(rows -> rows.iterator().next().getInteger(0));
    }

    /**
     * 查询用户累计提现总金额
     *
     * @param userId 用户ID
     * @return 累计提现总金额（单位：分）
     */
    public Uni<BigDecimal> sumTotalWithdrawalAmount(Long userId) {
        String sql = "SELECT COALESCE(SUM(amount), 0) FROM wz_user_withdrawals WHERE user_id = $1";
        return client.preparedQuery(sql)
                .execute(Tuple.of(userId))
                .onItem().transform(rows -> rows.iterator().next().getBigDecimal(0));
    }

    /**
     * 查询用户最后一次提现成功的时间
     *
     * @param userId 用户ID
     * @return 最后一次提现成功的时间，如果没有则返回null
     */
    public Uni<LocalDateTime> getLastSuccessfulWithdrawalTime(Long userId) {
        String sql = "SELECT completed_time FROM wz_user_withdrawals WHERE user_id = $1 AND status = $2 ORDER BY completed_time DESC LIMIT 1";
        return client.preparedQuery(sql)
                .execute(Tuple.of(userId, WithdrawalStatus.SUCCESS.getCode()))
                .onItem().transform(rows -> {
                    if (rows.size() > 0) {
                        return rows.iterator().next().getLocalDateTime(0);
                    }
                    return null;
                });
    }

    /**
     * 根据ID查询提现记录
     *
     * @param id 提现记录ID
     * @return 提现记录
     */
    public Uni<UserWithdrawal> findById(Long id) {
        String sql = "SELECT * FROM wz_user_withdrawals WHERE id = $1";
        return client.preparedQuery(sql)
                .execute(Tuple.of(id))
                .onItem().transform(rows -> {
                    if (rows.size() > 0) {
                        return mapRowToUserWithdrawal(rows.iterator().next());
                    }
                    return null;
                });
    }

    /**
     * 保存用户提现记录，同步保存用户提现面板（更新或创建，根据用户id）
     * 实现显式锁定账户和原子化更新余额
     *
     * @param userWithdrawal 提现记录对象
     * @return 返回最新的提现记录
     */
    public Uni<UserWithdrawal> addWithdraw(UserWithdrawal userWithdrawal) {
        // 使用事务来执行操作
        return client.withTransaction(conn -> {
            Long userId = userWithdrawal.getUserId();
            BigDecimal amount = userWithdrawal.getAmount(); //提现金额，单位分

            // 1. 显式锁定账户行，阻止其他事务并发修改
            String lockAccountSql = "SELECT * FROM wz_user_accounts WHERE user_id = $1 FOR UPDATE";

            return conn.preparedQuery(lockAccountSql)
                    .execute(Tuple.of(userId))
                    .onItem().transformToUni(lockRows -> {
                        if (lockRows.size() == 0) {
                            LOG.errorf("用户%s账户不存在", userId);
                            throw new RuntimeException("账户不存在");
                        }

                        // 获取账户行数据
                        Row accountRow = lockRows.iterator().next();
                        Long accountId = accountRow.getLong("id");

                        // 2. 插入账变记录
                        String changeSql = "INSERT INTO wz_user_account_changes (user_id, account_id, change_type, change_amount, balance_before, balance_after, related_order_no, remark, created_at,bs_ac,trans_id,sys_remark,from_user_id) " +
                                "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9,$10,$11,$12,$13) RETURNING id";

                        BigDecimal balance = accountRow.getBigDecimal("balance");
                        Tuple tuple = Tuple.from(Arrays.asList(
                                accountRow.getLong("user_id"),
                                accountRow.getLong("id"),
                                AccountChangeType.FROZEN.getCode(),//冻结
                                amount, // 提现金额，单位分
                                balance, // 变更前余额，单位分
                                balance.subtract(amount).setScale(6, RoundingMode.DOWN), // 变更后余额
                                userWithdrawal.getWithdrawalNo(), //订单号
                                "提现申请冻结",
                                LocalDateTime.now(),
                                3,//冻结
                                userWithdrawal.getWithdrawalNo(), //事务号，即：订单号
                                "提现申请，冻结",
                                accountRow.getLong("user_id")
                        ));

                        return conn.preparedQuery(changeSql)
                                .execute(tuple)
                                .onItem().transformToUni(changeRows -> {
                                    // 3. 原子化更新余额
                                    String updateBalanceSql = "UPDATE wz_user_accounts " +
                                            "SET balance = balance - $1, frozen_balance = frozen_balance + $1 " +
                                            "WHERE user_id = $2 AND balance >= $1 " +
                                            "RETURNING *";

                                    return conn.preparedQuery(updateBalanceSql)
                                            .execute(Tuple.of(amount, userId))
                                            .onItem().transformToUni(updateRows -> {
                                                if (updateRows.size() == 0) {
                                                    LOG.errorf("用户%s余额不足，提现金额：%s", userId, amount);
                                                    throw new RuntimeException("余额不足，提现失败");
                                                }

                                                // 3. 插入提现记录到wz_user_withdrawals表
                                                String insertWithdrawalSql = "INSERT INTO wz_user_withdrawals (withdrawal_no, user_id, amount, withdrawal_type, " +
                                                        "withdrawal_channel, account_info, status, audit_status, audit_time, audit_admin_id, " +
                                                        "audit_remark, completed_time, failure_reason, third_party_order_no, remark,payment_type,trans_action) " +
                                                        "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15,$16,$17) RETURNING *";

                                                Tuple withdrawalTuple = getTupleFromWithdrawPojo(userWithdrawal);

                                                return conn.preparedQuery(insertWithdrawalSql)
                                                        .execute(withdrawalTuple)
                                                        .onItem().transform(insertRows -> {
                                                            if (insertRows.size() > 0) {
                                                                return mapRowToUserWithdrawal(insertRows.iterator().next());
                                                            }
                                                            LOG.errorf("插入提现记录失败");
                                                            throw new RuntimeException("插入提现记录失败");
                                                        });
                                            })
                                            .onFailure().invoke(throwable -> {
                                                LOG.errorf("更新用户%s余额失败: %s", userId, throwable.getMessage());
                                                throw new RuntimeException("提现失败，系统异常");
                                            });
                                })
                                .onFailure().invoke(throwable -> {
                                    LOG.errorf("提现事务执行失败: %s", throwable.getMessage());
                                    throw new RuntimeException("提现失败");
                                });
                    });
        });
    }

    private static Tuple getTupleFromWithdrawPojo(UserWithdrawal userWithdrawal) {
        Tuple withdrawalTuple = Tuple.from(Arrays.asList(
                userWithdrawal.getWithdrawalNo(),
                userWithdrawal.getUserId(),
                userWithdrawal.getAmount(),
                userWithdrawal.getWithdrawalType(),
                userWithdrawal.getWithdrawalChannel(),
                userWithdrawal.getAccountInfo(),
                userWithdrawal.getStatus(),
                userWithdrawal.getAuditStatus(),
                userWithdrawal.getAuditTime(),
                userWithdrawal.getAuditAdminId(),
                userWithdrawal.getAuditRemark(),
                userWithdrawal.getCompletedTime(),
                userWithdrawal.getFailureReason(),
                userWithdrawal.getThirdPartyOrderNo(),
                userWithdrawal.getRemark(),
                userWithdrawal.getPaymentType(),
                userWithdrawal.getTransAction()
        ));
        return withdrawalTuple;
    }

    private Tuple getTupleOfInsert(WithdrawSummary withdrawSummary, UserWithdrawal savedWithdrawal) {

        // 将Map转换为JSON字符串
        String amountItemsJson = null;
        try {
            if (withdrawSummary.getAmountItems() != null) {
                amountItemsJson = objectMapper.writeValueAsString(withdrawSummary.getAmountItems());
            }
        } catch (Exception e) {
            LOG.error("Failed to convert amountItems to JSON", e);
        }

        Tuple insertSummaryTuple = Tuple.from(Arrays.asList(
                savedWithdrawal.getUserId(),
                withdrawSummary.getLastTime(),
                withdrawSummary.getLastStatus(),
                withdrawSummary.getDailyCount(),
                withdrawSummary.getDailySuccessCount(),
                withdrawSummary.getDailyPendingCount(),
                withdrawSummary.getDailyAmount(),
                withdrawSummary.getDailySuccessAmount(),
                withdrawSummary.getDailyPendingAmount(),
                amountItemsJson != null ? new JsonObject(amountItemsJson) : null,
                withdrawSummary.getTotalAmount()
        ));
        return insertSummaryTuple;
    }

    /**
     * 将数据库行映射为UserWithdrawal对象
     *
     * @param row 数据库行
     * @return UserWithdrawal对象
     */
    private UserWithdrawal mapRowToUserWithdrawal(Row row) {
        UserWithdrawal withdrawal = new UserWithdrawal();
        withdrawal.setId(row.getLong("id"));
        withdrawal.setWithdrawalNo(row.getString("withdrawal_no"));
        withdrawal.setUserId(row.getLong("user_id"));
        withdrawal.setAmount(row.getBigDecimal("amount"));
        withdrawal.setWithdrawalType(row.getInteger("withdrawal_type"));

        // 处理枚举类型
        withdrawal.setWithdrawalChannel(row.getInteger("withdrawal_channel"));
        withdrawal.setStatus(row.getInteger("status"));
        withdrawal.setAuditStatus(row.getInteger("audit_status"));

        withdrawal.setAccountInfo(row.getString("account_info"));
        withdrawal.setAuditTime(row.getLocalDateTime("audit_time"));
        withdrawal.setAuditAdminId(row.getLong("audit_admin_id"));
        withdrawal.setAuditRemark(row.getString("audit_remark"));
        withdrawal.setCompletedTime(row.getLocalDateTime("completed_time"));
        withdrawal.setFailureReason(row.getString("failure_reason"));
        withdrawal.setThirdPartyOrderNo(row.getString("third_party_order_no"));
        withdrawal.setRemark(row.getString("remark"));
        withdrawal.setCreatedAt(row.getLocalDateTime("created_at"));
        withdrawal.setUpdatedAt(row.getLocalDateTime("updated_at"));
        withdrawal.setPaymentType(row.getInteger("payment_type"));
        withdrawal.setTransAction(row.getInteger("trans_action"));
        return withdrawal;
    }

    /**
     * 根据代码获取WithdrawalChannel枚举
     */
    private WithdrawalChannel getWithdrawalChannelByCode(int code) {
        for (WithdrawalChannel channel : WithdrawalChannel.values()) {
            if (channel.getCode() == code) {
                return channel;
            }
        }
        return null;
    }

    /**
     * 根据代码获取WithdrawalStatus枚举
     */
    private WithdrawalStatus getWithdrawalStatusByCode(int code) {
        for (WithdrawalStatus status : WithdrawalStatus.values()) {
            if (status.getCode() == code) {
                return status;
            }
        }
        return null;
    }

    /**
     * 根据代码获取AuditStatus枚举
     */
    private AuditStatus getAuditStatusByCode(int code) {
        for (AuditStatus status : AuditStatus.values()) {
            if (status.getCode() == code) {
                return status;
            }
        }
        return null;
    }

    /**
     * 查询用户的提现记录列表
     *
     * @param userId 用户ID
     * @return 提现记录列表
     */
    public Uni<List<UserWithdrawal>> getUserWithdrawalSummary(Long userId) {
        String sql = "SELECT * FROM wz_user_withdrawals WHERE user_id = $1 ORDER BY created_at DESC";

        return client.preparedQuery(sql)
                .execute(Tuple.of(userId))
                .onItem().transform(rows -> {
                    List<UserWithdrawal> resultList = new ArrayList<>();
                    for (Row row : rows) {
                        resultList.add(mapRowToUserWithdrawal(row));
                    }
                    return resultList;
                });
    }


    public Uni<List<UserBindWithdrawRelation>> findUserWithdrawRelationByUser(Long userid) {
        String sql = "SELECT a.* FROM wz_user_bind_withdraw_relation a WHERE a.user_id is not null and a.user_id = $1";
        return client.preparedQuery(sql).execute(Tuple.of(userid)).onItem().transform(rows -> {
            List<UserBindWithdrawRelation> configs = new ArrayList<>();
            for (Row row : rows) {
                configs.add(mapRowToRealnameRelation(row));
            }
            return configs;
        });
    }

    public Uni<WithdrawSummary> getWithdrawDashboardByUser(Long userid) {
        // 构建基础查询条件
        StringBuilder sql = new StringBuilder();

        // 添加基础筛选条件
        // 累计提现金额 (状态为成功)
        sql.append("WITH today_data AS (" +
                "     SELECT" +
                "         ROUND(CAST(amount AS numeric) / 100, 2)::text AS amount_key," +
                "         user_id AS wz_user_id," +
                "        COUNT(*) FILTER (WHERE status != 3) AS total_withdrawal_count," +
                "        COUNT(*) FILTER (WHERE status = 2) AS total_success_withdrawal_count," +
                "         COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE) AS today_count," +
                "         COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE AND status = 2) AS today_success_count," +
                "         COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE AND status IN (1,4)) AS today_processing_count," +
                "         COALESCE(ROUND(CAST(SUM(CASE WHEN created_at::date = CURRENT_DATE THEN amount END) AS numeric) / 100, 2), 0) AS today_amount," +
                "         COALESCE(ROUND(CAST(SUM(CASE WHEN created_at::date = CURRENT_DATE AND status = 2 THEN amount END) AS numeric) / 100, 2), 0) AS today_success_amount," +
                "         COALESCE(ROUND(CAST(SUM(CASE WHEN created_at::date = CURRENT_DATE AND status IN (1,4) THEN amount END) AS numeric) / 100, 2), 0) AS today_processing_amount" +
                "     FROM wz_user_withdrawals" +
                "     WHERE user_id = $1" +
                "     GROUP BY ROUND(CAST(amount AS numeric) / 100, 2), wz_user_id" +
                " )" +
                " SELECT" +
                "     w.user_id," +
                "     MAX(created_at) AS last_withdrawal_time," +
                "     (SELECT status FROM wz_user_withdrawals" +
                "      WHERE user_id = w.user_id" +
                "      ORDER BY created_at DESC LIMIT 1) AS last_withdrawal_status," +
                "     (SELECT COUNT(*) FROM wz_user_withdrawals" +
                "      WHERE user_id = w.user_id AND created_at::date = CURRENT_DATE) AS today_total_count," +
                "     (SELECT COUNT(*) FROM wz_user_withdrawals" +
                "      WHERE user_id = w.user_id AND created_at::date = CURRENT_DATE AND status = 2) AS today_success_count," +
                "     (SELECT COUNT(*) FROM wz_user_withdrawals" +
                "      WHERE user_id = w.user_id AND created_at::date = CURRENT_DATE AND status IN (1,4)) AS today_processing_count," +
                "     COALESCE(SUM(today_amount), 0) AS today_total_amount," +
                "     COALESCE(SUM(today_success_amount), 0) AS today_success_amount," +
                "     COALESCE(SUM(today_processing_amount), 0) AS today_processing_amount," +
                "     JSONB_OBJECT_AGG(" +
                "             amount_key," +
                "             JSONB_BUILD_OBJECT(" +
                "                     'today_count', today_count," +
                "                     'today_success_count', today_success_count," +
                "                     'today_processing_count', today_processing_count," +
                "                     'total_withdrawal_count', total_withdrawal_count, " +
                "                    'total_success_withdrawal_count', total_success_withdrawal_count," +
                "                     'today_amount', COALESCE(today_amount, 0)," +
                "                     'today_success_amount', COALESCE(today_success_amount, 0)," +
                "                     'today_processing_amount', COALESCE(today_processing_amount, 0)" +
                "             )" +
                "     ) AS user_amount_details," +
                "     COALESCE(ROUND(CAST(SUM(amount) AS numeric) / 100, 2), 0) AS total_withdrawal_amount" +
                " FROM wz_user_withdrawals w" +
                "          LEFT JOIN today_data ON w.user_id = today_data.wz_user_id" +
                " WHERE w.user_id = $2" +
                " GROUP BY w.user_id ");
        List<Object> params = Arrays.asList(userid, userid);

        return client.preparedQuery(sql.toString())
                .execute(Tuple.from(params))
                .onItem().transform(rows -> {
                    if (rows.size() > 0) {
                        WithdrawSummary dashboard = new WithdrawSummary();
                        Row row = rows.iterator().next();
                        dashboard.setLastTime(row.getLocalDateTime("last_withdrawal_time"));//最后提现时间
                        dashboard.setLastStatus(row.getInteger("last_withdrawal_status")); //最后提现状态
                        dashboard.setTotalAmount(row.getBigDecimal("total_withdrawal_amount"));//累计提现总金额
                        dashboard.setUserId(userid);

                        dashboard.setDailyAmount(row.getBigDecimal("today_total_amount")); //今日累计提现金额
                        dashboard.setDailyCount(row.getInteger("today_total_count"));//今日累计提现次数
                        dashboard.setDailyPendingAmount(row.getBigDecimal("today_processing_amount"));//今日等待处理的金额
                        dashboard.setDailyPendingCount(row.getInteger("today_processing_count"));//今日等待处理的次数
                        dashboard.setDailySuccessAmount(row.getBigDecimal("today_success_amount"));//今日成功提现金额
                        dashboard.setDailySuccessCount(row.getInteger("today_success_count"));//今日成功提现次数
                        JsonObject userAmountDetails = row.getJsonObject("user_amount_details");
                        if (userAmountDetails != null) {
                            Map<String, WithdrawUserSummaryItem> itemMap = JsonMapUtil.parseObject(userAmountDetails.toString(), new TypeReference<>() {
                            });
                            dashboard.setAmountItems(itemMap);
                        }
                        return dashboard;
                    }
                    return createEmptyWithdrawSummary(userid);
                }).onFailure().recoverWithUni(throwable -> {
                    LOG.errorf(throwable, "保存错误");
                    throw new RuntimeException("");
                });
    }

    private WithdrawSummary createEmptyWithdrawSummary(Long userId) {
        WithdrawSummary summary = new WithdrawSummary();
        summary.setUserId(userId);
        summary.setDailyCount(0);
        summary.setDailySuccessCount(0);
        summary.setDailyPendingCount(0);
        summary.setDailyAmount(BigDecimal.ZERO);
        summary.setDailySuccessAmount(BigDecimal.ZERO);
        summary.setDailyPendingAmount(BigDecimal.ZERO);
        summary.setAmountItems(new HashMap<>());
        summary.setTotalAmount(BigDecimal.ZERO);
        summary.setLastTime(LocalDateTime.now());
        return summary;
    }


    /**
     * 插入
     *
     * @param bindWithdrawRelation
     * @return
     */
    public Uni<UserBindWithdrawRelation> insertBindWithdrawResult(UserBindWithdrawRelation bindWithdrawRelation) {

        List<String> insertColumns = Arrays.asList("user_id", "withdraw_channel", "payment_type", "simple_name", "details_info");

        // 列名拼接
        String columns = String.join(", ", insertColumns);

        // 动态生成占位符（$1, $2, $3...）
        List<String> placeholderList = new ArrayList<>();
        for (int i = 0; i < insertColumns.size(); i++) {
            placeholderList.add("$" + (i + 1));
        }
        String placeholders = String.join(", ", placeholderList);

        String sql = String.format(
                "INSERT INTO wz_user_bind_withdraw_relation (%s) VALUES (%s)  RETURNING *",
                columns,
                placeholders
        );

        Tuple tuple = Tuple.from(Arrays.asList(bindWithdrawRelation.getUserid(), bindWithdrawRelation.getWithdrawChannel(), bindWithdrawRelation.getPaymentType(), bindWithdrawRelation.getSimpleName(), bindWithdrawRelation.getDetailsInfo()));

        return client.preparedQuery(sql.toString())
                .execute(tuple)
                .onItem().transformToUni(rows -> Uni.createFrom().item(bindWithdrawRelation));
    }


    private UserBindWithdrawRelation mapRowToRealnameRelation(Row row) {
        UserBindWithdrawRelation account = new UserBindWithdrawRelation();
        account.setUserid(row.getLong("user_id"));
        account.setPaymentType(row.getInteger("payment_type")); //用户端描述
        account.setWithdrawChannel(row.getInteger("withdraw_channel")); //用户端描述
        account.setSimpleName(row.getString("simple_name"));
        return account;
    }

    /**
     * 将数据库行映射为WithdrawSummary对象
     *
     * @param row 数据库行
     * @return WithdrawSummary对象
     */
    private WithdrawSummary mapRowToWithdrawSummary(Row row) {
        WithdrawSummary summary = new WithdrawSummary();
        summary.setUserId(row.getLong("user_id"));
        summary.setLastTime(row.getLocalDateTime("last_time"));
        summary.setLastStatus(row.getInteger("last_status"));
        summary.setDailyCount(row.getInteger("daily_count"));
        summary.setDailySuccessCount(row.getInteger("daily_success_count"));
        summary.setDailyPendingCount(row.getInteger("daily_pending_count"));
        summary.setDailyAmount(row.getBigDecimal("daily_amount"));
        summary.setDailySuccessAmount(row.getBigDecimal("daily_success_amount"));
        summary.setDailyPendingAmount(row.getBigDecimal("daily_pending_amount"));
        // 假设数据库中amount_items字段是json类型，获取后解析为Map<String, List<WithdrawUserSummaryItem>>
        JsonObject amountItemsJson = row.getJsonObject("amount_items");
        // 这里需要根据实际的JSON解析库实现解析逻辑，示例中假设已有工具方法parseJsonToMap
        summary.setAmountItems(parseJsonToMap(amountItemsJson));
        summary.setTotalAmount(row.getBigDecimal("total_amount")); //累计提现金额
        return summary;
    }

    private WithdrawRecordResponseDto mapRowToPageRecord(Row row) {
        WithdrawRecordResponseDto summary = new WithdrawRecordResponseDto();
        summary.setAmount(row.getBigDecimal("amount"));
        summary.setRequestTime(row.getLocalDateTime("created_at"));
        summary.setStatus(row.getInteger("status"));
        return summary;
    }

    /**
     * 将JSON对象解析为Map<String, List<WithdrawUserSummaryItem>>
     *
     * @param jsonObject JSON对象
     * @return 解析后的Map，如果解析失败则返回空Map
     */
    private Map<String, WithdrawUserSummaryItem> parseJsonToMap(JsonObject jsonObject) {
        Map<String, WithdrawUserSummaryItem> resultMap = new HashMap<>();

        if (jsonObject == null) {
            return resultMap;
        }

        try {
            // 使用Jackson的ObjectMapper直接转换类型
            // 先将JsonObject转换为字符串
            String jsonString = jsonObject.encode();

            // 定义TypeReference来指定泛型类型
            TypeReference<Map<String, WithdrawUserSummaryItem>> typeRef = new TypeReference<>() {
            };

            // 使用ObjectMapper强转类型
            resultMap = objectMapper.readValue(jsonString, typeRef);
        } catch (Exception e) {
            // 记录错误日志，但不终止程序运行
            LOG.error("Failed to parse JSON to Map<String, List<WithdrawUserSummaryItem>>", e);
        }

        return resultMap != null ? resultMap : new HashMap<>();
    }
}